package com.bearhy.jqadmin.config;

import com.bearhy.jqadmin.model.SysMenu;
import com.bearhy.jqadmin.service.SysMenuService;
import com.bearhy.jqadmin.shiro.MShiroFilterFactoryBean;
import com.bearhy.jqadmin.shiro.MyShiroRealm;
import com.github.pagehelper.util.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
public class ShiroConfig {
    private static final Log log = LogFactory.getLog(ShiroConfig.class);

    @Autowired
    private SysMenuService sysMenuService;

    /**
     * 过滤前端静态两种方式
     * 1、filterMap添加过滤权限
     *    filterMap.put("/js/**","anon");
     * 2、使用 MShiroFilterFactoryBean自定义拦截器处理类
     *    ShiroFilterFactoryBean bean = new MShiroFilterFactoryBean();
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
        System.out.println("ShiroConfiguration.shirFilter()");
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager);
        Map<String,String> filterMap=new LinkedHashMap<>();
        filterMap.put("/js/**","anon");
        filterMap.put("/css/**","anon");
        filterMap.put("/images/**","anon");
        filterMap.put("/fonts/**","anon");
        filterMap.put("/logout","logout");
        //从数据库读取权限，拼接格式 /admin/listUser**=authc,perms[admin:manage]
        log.info("######从数据库读取权限规则，加载到shiroFilter中######");
        List<SysMenu> menus = sysMenuService.getMenuPermissions();
        for (SysMenu menu : menus) {
            if(StringUtil.isNotEmpty(menu.getMenuPerms())){
                String fm = filterMap.get(menu.getMenuUrl());
                if(StringUtil.isNotEmpty(fm)){
                    StringBuffer sb = new StringBuffer();
                    sb.append(fm).insert(fm.indexOf("]"),","+menu.getMenuPerms());
                    filterMap.put(menu.getMenuUrl(),sb.toString());
                }else{
                    String p = "authc,perms["+menu.getMenuPerms()+"]";
                    filterMap.put(menu.getMenuUrl(),p);
                }
                //log.info("加载权限："+menu.getMenuUrl()+"="+p);
            }
        }
        filterMap.put("/**","authc");
        bean.setLoginUrl("/login");
        bean.setSuccessUrl("/index");
        bean.setUnauthorizedUrl("/403");
        bean.setFilterChainDefinitionMap(filterMap);
        return bean;
    }

    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        //散列的次数，比如散列两次，相当于 md5(md5(""));
        hashedCredentialsMatcher.setHashIterations(1024);
        return hashedCredentialsMatcher;
    }

    @Bean
    public MyShiroRealm myShiroRealm(){
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myShiroRealm;
    }

    /**
     * 加密测试
     * @param args
     */
    public static void main(String[] args) {
        String hashAlgorithmName = "MD5";
        String credentials = "admin123";
        int hashIterations = 1024;
        String salt = "bearhy";
        Object obj = new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
        System.out.println(obj);
    }

}
